package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.schedule.dto.Task;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.ProtostuffUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.UserThreadLocal;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.swing.*;
import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private AutoScanService autoScanService;
    @Autowired
    private IScheduleClient scheduleClient;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private IArticleClient articleClient;


    @Override
    public PageResponseResult list(WmNewsPageReqDto dto) {
        if (dto == null) {
            return new PageResponseResult(0, 0, 0);
        }

        //查询频道
        Integer channelId = dto.getChannelId();
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(channelId != null, WmNews::getChannelId, channelId);

        //查询发布时间范围
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();
        wrapper.between(beginPubDate != null && endPubDate != null, WmNews::getPublishTime, beginPubDate, endPubDate);

        //关键字 模糊查找关键词  标题
        String keyword = dto.getKeyword();
        wrapper.like(StringUtils.isNotEmpty(keyword), WmNews::getTitle, keyword);

        //查询状态
        Short status = dto.getStatus();
        wrapper.eq(status != null, WmNews::getStatus, status);

        //根据用户查询
        wrapper.eq(WmNews::getUserId, UserThreadLocal.get().getId());

        //排序
        wrapper.orderByDesc(WmNews::getPublishTime);

        //  构建分页 组装返回值
        Integer currentPage = dto.getPage();
        Integer size = dto.getSize();
        Page<WmNews> page = new Page<>(currentPage, size);

        Page<WmNews> wmNewsPage = wmNewsMapper.selectPage(page, wrapper);
        Long total = wmNewsPage.getTotal();
        PageResponseResult pageResponseResult = new PageResponseResult(currentPage, size, total.intValue());
        pageResponseResult.setData(wmNewsPage.getRecords());
        return pageResponseResult;
    }


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult submit(WmNewsDto wmNewsDto) {
        //提取新闻内容
        WmNews wmNews = wmNewsDtoWnNews(wmNewsDto);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //插入新闻表
        int insert = wmNewsMapper.insert(wmNews);
        if (insert < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }

        //判断是否为草稿
        Short status = wmNewsDto.getStatus();
        if (status == 0) {
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

        //提取内容图
        String content = wmNewsDto.getContent();
        List<String> contentImages = getContentImages(content);

        //自动布局
        List<String> images = wmNewsDto.getImages();
        Short type = wmNewsDto.getType();
        //提取封面图
        List<String> coverImages = getCoverImages(type, images, contentImages);

        //插入内容图
        Boolean contentImageResult = addMaterial(wmNews.getId(), contentImages, 0);
        if (!contentImageResult) {
            throw new RuntimeException("内容图添加失败");
        }
        //插入封面图
        Boolean coverImageResult = addMaterial(wmNews.getId(), coverImages, 1);
        if (!coverImageResult) {
            throw new RuntimeException("封面图图添加失败");
        }

//        //调用审核代码
//        try {
//            autoScanService.autoScanWmNews(wmNews.getId().longValue());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        //发布任务的需求
        Boolean addToTaskResult = addToTask(wmNews.getId(), wmNews.getPublishTime().getTime());
        if (!addToTaskResult) {
            log.warn("任务添加失败");
            throw new RuntimeException("任务添加失败");
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    //自媒体文章上下架


    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //查询新闻
        Integer id = dto.getId();
        WmNews wmNews = wmNewsMapper.selectById(id);

        //新闻是否为空
        if (wmNews == null) {
            log.warn("新闻不存在");
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "新闻不存在");
        }
        Short status = wmNews.getStatus();
        if (status != 9) {
            log.warn("当前文章状态不能上架");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前文章状态不能上架");
        }

        //修改新闻的enable字段
        wmNews.setEnable(dto.getEnable());
        int update = wmNewsMapper.updateById(wmNews);
        if (update < 1) {
            log.warn("文章更新失败");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "文章更新失败");
        }

        //向kafaka中发送消息 articleId  enable
        Map<String, Object> map = new HashMap<>();

        Long articleId = wmNews.getArticleId();
        Short enable = wmNews.getEnable();

        map.put("articleId", articleId);
        map.put("enable", enable);
        kafkaTemplate.send("news.down.up.topic", JSON.toJSONString(map));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    //文章审核
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult passOrFail(NewsAuthDto dto, Integer type) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //根据id查询新闻
        Integer id = dto.getId();
        String msg = dto.getMsg();
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //根据id修改新闻状态
        int status = type == 1 ? 9 : 2;
        wmNews.setStatus((short) status);
        wmNews.setReason(type == 1 ? "通过" : msg);

//        调用article.saveArticle()
        int updateResult = wmNewsMapper.updateById(wmNews);
        if (updateResult < 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "新闻审核失败");
        }
        if (type == 1) {
            ArticleDto articleDto = autoScanService.WmNews2ArticleDto(wmNews);
            ResponseResult responseResult = articleClient.saveArticle(articleDto);
            //判断响应结果是不是200
            if (responseResult == null || responseResult.getCode() != 200) {
                log.warn("文章保存失败");
                throw new RuntimeException("文章审核失败");
            }
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult findList(NewsAuthDto dto) {
        //参数检查
        dto.checkParam();
        Integer page = dto.getPage();
        Page<WmNews> wmNewsPage = new Page<>();
        Page<WmNews> pageResult = wmNewsMapper.selectPage(wmNewsPage, null);
        //结果返回
        long total = pageResult.getTotal();
        ResponseResult responseResult = new PageResponseResult(page, dto.getSize(), (int) total);
        responseResult.setData(pageResult.getRecords());
        return responseResult;
    }

    private Boolean addToTask(Integer newsId, Long execueTime) {

        Task task = new Task();
        task.setExecuteTime(execueTime);

        WmNews wmNews = new WmNews();
        wmNews.setId(newsId);

        task.setParameters(ProtostuffUtil.serialize(wmNews));//序列化工具类 转byte

        ResponseResult responseResult = scheduleClient.addTask(task);
        if (responseResult != null && responseResult.getCode() == 200) {
            return true;
        }

        return false;
    }

    //提取新闻内容
    public WmNews wmNewsDtoWnNews(WmNewsDto wmNewsDto) {
        if (wmNewsDto == null) {
            return null;
        }
        WmNews wmNews = new WmNews();
        //自动映射
        //dto和wmNews相同字段进行赋值
        BeanUtils.copyProperties(wmNewsDto, wmNews);
        //差异的字段
        wmNews.setUserId(UserThreadLocal.get().getId());
        if (wmNewsDto.getType() == -1) {
            wmNews.setType(null);
        }
        wmNews.setCreatedTime(new Date());
        wmNews.setEnable((short) 1);

        List<String> images = wmNewsDto.getImages();
        if (!CollectionUtils.isEmpty(images)) {
            String join = StringUtils.join(images, ",");
            wmNews.setImages(join);
        }
        return wmNews;
    }

    //提取内容图
    public List<String> getContentImages(String context) {
        if (StringUtils.isEmpty(context)) {
            return new ArrayList<>();
        }

        List<String> urllist = new ArrayList<>();
        //将context转为集合
        //遍历集合，找到里面type = image数据
        List<Map> maps = JSON.parseArray(context, Map.class);
        //先判空
        if (CollectionUtils.isEmpty(maps)) {
            return new ArrayList<>();
        }
        for (Map map : maps) {
            if (CollectionUtils.isEmpty(map)) {
                continue;
            }
            Object type = map.get("type");
            if ("images".equals(type)) {
                String value = (String) map.get("value");
                urllist.add(value);
            }
        }
        return urllist;
    }

    private List<String> getCoverImages(Short type, List<String> images, List<String> contentImages) {
        //自动布局
        if (type == -1) {
            //判断内容图数量 》=3
            int size = contentImages.size();
            if (size >= 3) {
                return contentImages.subList(0, 2);
            } else if (size == 2) {
                return contentImages.subList(0, 1);
            } else if (size == 1) {
                List<String> list = new ArrayList<>();
                list.add(contentImages.get(0));
                return list;
                //封面图
            } else {
                return new ArrayList<>();
            }
        }
        return images;
    }

    //插入内容图 0内容  1封面
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean addMaterial(Integer newsId, List<String> imageList, Integer type) {
        //遍历
        //添加素材
        //添加素材和新闻关系
        if (CollectionUtils.isEmpty(imageList)) {
            return true;
        }
        for (String url : imageList) {
            if (StringUtils.isEmpty(url)) {
                continue;
            }
            WmMaterial wmMaterial = new WmMaterial();
            wmMaterial.setUserId(UserThreadLocal.get().getId());
            wmMaterial.setUrl(url);
            wmMaterial.setType((short) 0);
            wmMaterial.setIsCollection((short) 0);
            wmMaterial.setCreatedTime(new Date());
            int insert = wmMaterialMapper.insert(wmMaterial);
            if (insert < 1) {
                throw new RuntimeException("素材添加失败");
            }
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setNewsId(newsId);
            wmNewsMaterial.setType(type.shortValue());
            wmNewsMaterial.setOrd((short) 1);
            wmNewsMaterial.setMaterialId(wmMaterial.getId());
            int insert2 = wmNewsMaterialMapper.insert(wmNewsMaterial);
            if (insert2 < 1) {
                throw new RuntimeException("素材关系添加失败");
            }
        }
        return true;
    }
}
